﻿#ifndef BUSINESSSQL_H
#define BUSINESSSQL_H

#include <nlohmann/json.hpp>

#include <sqlite3.h>

#include <soci/soci.h>
#include <soci/mysql/soci-mysql.h>

class BusinessSQL
{
public:
    // 删除拷贝构造函数和拷贝赋值操作符
    BusinessSQL(BusinessSQL const&) = delete;
    BusinessSQL& operator=(BusinessSQL const&) = delete;
    // 提供一个全局唯一的接口
    static BusinessSQL& getInstance() {
        static BusinessSQL instance;
        return instance;
    }

    // init
    void init();
    // connect to a database
    void useDatabase();

    void createTable();

    void createAUser(const std::string& account, const std::string& password);


    // query all the friend
    nlohmann::json queryAllTheUserOfTargetRelation(const std::string& account, const std::string& relation = "accepted");

    // query a user according to id
    nlohmann::json queryAUser(uint64_t id);

    // query a user according to account
    nlohmann::json queryAUser(const std::string & account);

    // query a user with relation
    nlohmann::json quertAUserToUser(const std::string& applyAccount, const std::string& targetAccount);

    // query all the offline message of UserA to UserB
    nlohmann::json queryOffineMessage(uint64_t senderID, uint64_t receiverID);

    // store offline message to database
    void storeOfflineMessage(uint64_t senderID, uint64_t receiverID, std::string message);

    // update the status of a offline message
    void updateOfflineMessageStatus(int messageID);

    // verify a user
    bool verifyAUser(const std::string& account, const std::string& password);

    // query all the file
    nlohmann::json queryAllTheFile();

    // query if a file exists
    bool queryAFileExists(const std::string & fileName, int type);

    // insert a file
    void insertAFile(const std::string& fileName, uint64_t fileSize, int type);

    // query all file
    nlohmann::json queryAFile(uint64_t id);

    // 查询一个图片
    nlohmann::json queryAPicture(const std::string& fileName);

    // update friendship apply -> target
    void updateOrInsertFriendship(uint64_t applyID, uint64_t targetID, const std::string& status);

    // get status between user
    std::string getRelation(uint64_t user1, uint64_t user2);

    // erase friend
    void eraseFriend(uint64_t user1ID, uint64_t user2ID);

    std::pair<uint64_t, std::string> insertUserMessage(uint64_t senderID, uint64_t recvID, const std::string& message, const std::string& status, int messageType);

    // update avatar

    void updateAvatar(uint64_t userID, int avatar);


    //// group
    ///
    ///

    bool queryAGroupExists(const std::string& groupName);

    nlohmann::json queryAGroupInfo(const std::string& groupName);

    void createAGroup(const std::string& groupName, uint64_t userID);

    nlohmann::json findUserGroupsAndPosition(const std::string& account);

    void joinAGroup(uint64_t groupID, uint64_t userID, std::string status);
    // [messageID, time]
    std::pair<uint64_t, std::string> storeGroupMessage(uint64_t userID, uint64_t groupID, const std::string& message, int messageType);
    //[userid1, userid2]
    nlohmann::json getGroupMember(uint64_t groupID);

    void userLeaveGroup(uint64_t groupID, uint64_t userID);

    void deleteGroupMessage(uint64_t groupID);

    void deleteGroupMember(uint64_t groupID);

    void deleteGroup(uint64_t groupID);

    void acceptUserJoinGroupRequest(uint64_t groupID, uint64_t userID);

    void rejectUserJoinGroupRequest(uint64_t groupID, uint64_t userID);
    // [{group_id, applyID}]
    nlohmann::json getAllGroupRequest(const std::string& ownerName);
    // "GroupID" "UserID" "Message" "SendTime"
    nlohmann::json getLatest30GroupMessage(uint64_t groupID);

private:
    BusinessSQL();
    ~BusinessSQL() {}

    const int POOL_SIZE = 10;
    std::shared_ptr<soci::connection_pool> dbPool;

};

#endif // BUSINESSSQL_H
